<?php
class testsActions extends sfGraduaActions {

    public function executeIndex() {
        $this->setLayout('layoutTasks');
        $this->id = $this->getRequestParameter('id',null);

        $projectId = $this->getUser()->getAttribute('projectId');
        $project = ProjectsService::get($projectId);
        if(!$project['tests_dir_exists'] || !$project['tests_result_dir_exists'] ) {
            return sfView::ERROR;
        }
    }

    public function executeListTests() {
        $this->setLayout('layoutTasks');
        $search = $this->getRequestParameter('_search', null);
        if($search) {
            $fields = array('class','method','dir','result');
            $arSearch = array();
            foreach($fields as $field) {
                if($this->hasRequestParameter($field)) {
                    $arSearch[$field] = $this->getRequestParameter($field);
                }
            }
        }
        $obj = new stdClass;
        $obj->rows = $this->getRequestParameter('rows', null);
        $obj->page = $this->getRequestParameter('page', null);
        $obj->sortField = $this->getRequestParameter('sidx'  ,null);
        $obj->sortOrder = $this->getRequestParameter('sord'  ,null);
        $obj->search = $arSearch;
        $projectId = $this->getUser()->getAttribute('projectId');
        if($projectId) {
            $obj->projectId = $projectId;
        }
        else {
            throw new Exception("You need to choose a project to access this page.");
        }
        $ar = TestsService::getAll($obj);
        header('Content-type: application/x-json');
        die(json_encode($ar));
    }

    public function executeExtractDirs() {
        foreach(Doctrine::getTable('Test')->findAll() as $test) {
            $f = explode('/',$test->file);
            $test->dir = $f[1];
            $test->file = $f[2];
            $test->save();
        }
        die('super user;');
    }


    public function executeClearFilePaths() {
        foreach(Doctrine::getTable('Test')->findAll() as $test) {
            $ra = $test['result_attributes'];
            $file = $ra['file'];
            //echo $file;
            $i = '/essaylibrary/www/htdocs/essaylibrary/test/phpunit/';
            if( strpos($file,$i) !== false ) {
                //echo $file . '<br/>';
                // echo (substr($file,strlen($i))) . '<br/>';
                $test['file'] = substr($file,strlen($i));
            }
            $test->save();
        }
        die('Pronto!');
    }

    #### import routines and calculation
    public function executeImportTests() {
        $res = TestsService::importTests();
        $msg = sprintf(
            "imported %s tests from %s <br/>",
            $res['importedCount'],
            $res['dir']
        );
        $this->getUser()->setFlash('feedback',$msg);
        $this->redirect('tests/index');
    }

    public function executeImportResults() {
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $resultsDir = $project['tests_result_dir'];
        $msg = '';
        $importedSomething = false;
        foreach ( scandir($resultsDir) as $resultFile) {
            if(!in_array($resultFile,array('.','..'))) {
                $importedSomething = true;
                $resultPath = $resultsDir.DIRECTORY_SEPARATOR.$resultFile;
                $ret = TestTable::importTestResults($project['id'], $resultPath);
                $msg .= sprintf('<i>%s:</i><br/> &nbsp;%s tests updated',
                    $resultFile,
                    $ret['importedResultsCount']
                );
                if($ret['testNotFoundCount']) {
                    $msg .= ', %s tests not found.';
                }
                $msg .= '<br/>';
            }
        }
        if(!$importedSomething) {
            $msg = 'no result file found on: '.$resultsDir;
        }
        return $this->showJsCall(
            JsCall::build()
            ->showFeedback($msg)
            ->addCommand('tests.list','refresh')
        );
    }


    ############  Show List and Test Information

    /*public function executeShowTestList() {
        $tests = Doctrine::getTable('Test')->findAllTestsArrayOrderedByClass();
        sfLoader::loadHelpers(array('Partial','Php2Js'));
        $jsCall =
        JsCall::build()
        ->addCommand('TestListC','display')
        ->addPhpParam(
        'data',
            partial2Js('tests/list', array('tests'=>$tests), false)
        );
        if($this->hasRequestParameter('id')) {
            $jsCall
            ->addCommand('TestListC','scrollTo')
            ->addPhpParam('id',$this->getRequestParameter('id'));
        }

        return $this->showJsCall(
            $jsCall
        );
    }*/

    public function executeShowTest() {
        if(!$this->hasRequestParameter('id')) die('ID required');
        $id = $this->getRequestParameter('id');
        $test = Doctrine::getTable('Test')->find($id);
        sfLoader::loadHelpers(array('Partial','Php2Js','Url'));
        $this->getResponseJsCall()
            ->displayDialog(
            partial2Js(
                    'tests/test',
                array(
                        'test'=>$test,
                        'fileExists'=>$test->existsInFile(),
                        'development'=>sfConfig::get('app_development')
                ),
                false
            )
        )
        ->addPHPParam('width', 600);
        return sfView::NONE;
    }

    public function executeShowCreateTests() {
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $dir = $project['tests_dir'];
        sfLoader::loadHelpers(array('Partial','Php2Js'));
        $arChildren = array();
        $arDir = TestsService::createDirTreeStructure($dir);
        return $this->showJsCall(
            JsCall::build()
            ->addCommand('tests.tests','displayCreateTests')
            ->addPHPParam(
                'template',
                partial2Js('tests/createForm' , array(), false)
            )
            ->addPHPParam('treeSource',$arDir)
        );
    }

    public function executeCreateTests() {
        $data = $this->getObjRequest('tests');
        $data->existentClass = (boolean)$data->existentClass;
        $data->className = array_key_exists('className',$data) ? $data->className : '';
        $data->projectId = $this->getUser()->getAttribute('projectId');
        $firstSavedTestId = TestsService::create($data);
        return $this->showJsCall(
            JsCall::build()
            ->closeDialog()
            ->addCommand('tests.list','refresh')
            ->addPhpParam('id',$firstSavedTestId)
            ->showFeedback('Test(s) created. You might now write them to file if you are on a development environment.')
        );
    }

    public function executeWriteInFile() {
        $testId = $this->getRequestParameter('id');
        $test = Doctrine::getTable('Test')->find($testId);
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $testsDir = $project['tests_dir'];
        $file =
            $testsDir
            .DIRECTORY_SEPARATOR
            .$test->dir
            .DIRECTORY_SEPARATOR
            .$test->file;
        sfLoader::loadHelpers(array('Partial','Php2Js'));
        if(!file_exists($file)) {
            if(strpos(basename($test->file),'Selenium') !== false) {
                $partial = 'tests/codeSeleniumTestClass';
            }
            else {
                $partial = 'tests/codeTestClass';
            }
            // cria usando partial mesmo.
            $f = basename($test->file);
            $className = substr($f,0,strlen($f)-4);
            $code = get_partial(
                $partial,
                array(
                    'className' => $test->class,
                    'readableClassName' => $test->getReadableClassName()
                )
            );
            file_put_contents($file,"<?php\n".$code);
        }
        $methodCode = get_partial(
            'tests/codeTestMethod',
            array(
                'method' => $test->method,
                'readableMethodName' => $test->getReadableTestName()
            )
        );
        $fileCode = file_get_contents($file);
        $position = strrpos($fileCode,'}');
        $inicio = substr($fileCode,0,$position);
        $fim    = substr($fileCode,$position);
        $fileCode = $inicio.$methodCode."\n".$fim;
        file_put_contents($file,$fileCode);
        return $this->showJsCall(
            JsCall::build()
            ->addCommand('tests.tests','displayContent')
            ->addPhpParam(
                'data',
                partial2Js(
                    'tests/test',
                    array(
                        'test'=>$test,
                        'fileExists'=>$test->existsInFile(),
                        'development'=>sfConfig::get('app_development')
                    ),
                    false
                )
            )
            ->addCommand('tests.list','refresh')
            ->showFeedback('File succesfully written.')
        );
    }

    function executeRemoveFromDatabase() {
        $testId = $this->getRequestParameter('id');
        $test = Doctrine::getTable('Test')->find($testId);
        foreach($test->DevTaskTest as $rel) {
            $rel->delete();
        }
        $test->delete();
        return $this->showJsCall(
            JsCall::build()
            ->addCommand('tests.list','refresh')
            ->addCommand('tests.tests','hideTest')
            ->showFeedback('Test Removed.')
        );
    }

    ### run and open tests

    function executeRunTest() {
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $testsDir = $project['tests_dir'];
        $resultsDir = $project['tests_result_dir'];
        $this->unlinkOldResults($resultsDir);
        $testId = $this->getRequestParameter('testId');
        $class = $this->getRequestParameter('class',false);
        $test = Doctrine::getTable('Test')->find($testId);
        $dir =
            $testsDir.
            DIRECTORY_SEPARATOR.
            $test->dir;
        if(!$class) {
            $filter = '--filter '.$test->method;
        }
        $this->runTests($dir, $resultsDir, basename($test->file), $filter);
    }



    function unlinkOldResults($testResultsDir) {
        foreach ( scandir($testResultsDir) as $oldResultFile) {
            if(!in_array($oldResultFile,array('.','..'))) {
                $path = $testResultsDir.DIRECTORY_SEPARATOR.$oldResultFile;
                echo "unlink ".$path.'<br/>';
                unlink($path);
            }
        }
    }

    function executeRunTests() {
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $dir = $project['tests_dir'];
        $resultsDir = $project['tests_result_dir'];
        $this->unlinkOldResults($resultsDir);
        //$dirs = sfConfig::get('app_run_all_tests_dirs_order');
        $dirs = $this->getRequestParameter('dirs');
        $arDirs = explode( ',', $dirs );
        foreach($arDirs as &$d) {
            $d = trim($d);
        }
        $this->runTests($dir, $resultsDir, $arDirs);
    }

    function runTests($dir, $resultsDir, $filesOrDirs, $filter = '') {
        if(!is_array($filesOrDirs)) {
            $filesOrDirs = array($filesOrDirs);
        }
        
        $bufferOutputFile = sfConfig::get('app_phpunit_output_file');

        foreach($filesOrDirs as $i=>$fileOrDir) {
            $this->runTest($dir, $resultsDir, $fileOrDir, $filter);
            if(file_exists($bufferOutputFile)) {
                $c = file_get_contents($bufferOutputFile);
                echo "------------------\n<br/>".nl2br($c)."<br/>\n-----------------<br/>\n";
                unlink($bufferOutputFile);
            }
        }
        echo "\n<br/><b>TESTES CONCLUÍDOS</b>, agorá é só fechar esta janela ou aba e importar os resultados.";
        die();
    }

    function runTest($testsDir, $resultsDir, $fileOrDir, $filter = '') {
        $resultFile = $resultsDir.DIRECTORY_SEPARATOR.'testsResults_'.$fileOrDir.'.xml';
        $command =
        sprintf(
            sfConfig::get('app_phpunit_command_line'),
            $filter,
            $resultFile
        );
        $command .= $fileOrDir;
        $command = str_replace('/', DIRECTORY_SEPARATOR, $command);
        $command = str_replace('/', DIRECTORY_SEPARATOR, $command);
        //$command .= ' > '.sfConfig::get('app_phpunit_output_file');
        set_time_limit(0);
        echo '------------------------------------ <b>'.$fileOrDir.'</b><br/>';
        echo "<br/>";
        echo 'chdir "'.$testsDir.'"<br/>';
        chdir($testsDir);
        echo 'pwd <br/>'."\n";
        system('pwd');
        echo "<br/>\n";
        echo $command.'<br/>';
        echo "<pre>";
        flush();
        system($command);
        echo "</pre>";
    }

    function executeOpenTest() {
        $project = ProjectsService::get($this->getUser()->getAttribute('projectId'));
        $dir = $project['tests_dir'];
        $testId = $this->getRequestParameter('testId',null);
        $test = Doctrine::getTable('Test')->find($testId);
        $file =
            $dir
            .DIRECTORY_SEPARATOR
            .$test->dir
            .DIRECTORY_SEPARATOR
            .$test->file;
        ## get the line of the file, where the test is defined.
        require_once($file);
        try {
            $method = new ReflectionMethod($test->class,$test->method);
            $line = $method->getStartLine();
        }
        catch (ReflectionException $e) {
            return $this->showJsCall(
                JsCall::build()
                ->showFeedback('Method does not exist in file.')
            );
        }
        $lineCommand = ' ' . $line;
        $command = sprintf(
            sfConfig::get('app_editor_command'),
            //$line,
            $file
        );
        $this->execInBackground($command);
        return $this->showJsCall(
            JsCall::build()
            ->showFeedback('Editor Opened.')
        );
    }


    function executeShowError($request) {
        sfLoader::loadHelpers(array('Partial','Php2Js'));
        if(!$this->hasRequestParameter('id')) die('ID required');
        $id = $this->getRequestParameter('id');
        $test = Doctrine::getTable('Test')->find($id);
        $this->getResponseJsCall()
            ->displayDialog(
                partial2Js(
                    'tests/showError',
                    array(
                      'test'=>$test
                    ),
                    false
                )
            )
            ->addPhpParam('width',800)
            ->addPhpParam('height',300);
        return sfView::NONE;
    }

}
?>